import cv2
from PIL import Image, ImageEnhance, ImageFilter, ImageOps
import io
import base64
import numpy as np
from flask import jsonify, send_file, request
from io import BytesIO

def process_image(func):
    """装饰器：处理图像的通用流程"""
    def wrapper(image_data=None, *args, **kwargs):
        try:
            # 如果是 base64 字符串，先解码
            if isinstance(image_data, str) and image_data.startswith('data:image'):
                image_data = image_data.split(',')[1]
                image_bytes = base64.b64decode(image_data)
                img = Image.open(io.BytesIO(image_bytes))
            elif isinstance(image_data, str):
                img = Image.open(image_data)
            elif isinstance(image_data, Image.Image):
                img = image_data
            else:
                raise ValueError("不支持的图像数据格式")

            # 处理图像
            processed_img = func(img, *args, **kwargs)

            # 转换回 base64
            buffered = io.BytesIO()
            processed_img.save(buffered, format="PNG")
            img_str = base64.b64encode(buffered.getvalue()).decode()
            return {"image": f"data:image/png;base64,{img_str}"}

        except Exception as e:
            return {"error": str(e)}
    return wrapper

# 基础调整功能
@process_image
def resize_image(image, width, height, **kwargs):
    """调整图像大小"""
    resized_img = image.resize((width, height))
    return resized_img

@process_image
def adjust_quality(image, quality=95, **kwargs):
    """调整图像质量"""
    buffer = io.BytesIO()
    image.save(buffer, format='JPEG', quality=int(quality))
    return Image.open(buffer)

@process_image
def process_image(image_path, options):
    img = cv2.imread(image_path)
    # 1. 灰度化
    if 'gray' in options:
        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 2. 翻转
    if 'flip_horizontal' in options:
        img = cv2.flip(img, 1)
    if 'flip_vertical' in options:
        img = cv2.flip(img, 0)

    # 3. 裁剪 (固定大小)
    if 'crop' in options:
        height, width = img.shape[:2]
        img = img[int(height / 4):int(3 * height / 4), int(width / 4):int(3 * width / 4)]

    # 4. 旋转
    if 'rotate' in options:
        rows, cols = img.shape[:2]
        M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 45, 1)  # 旋转45度
        img = cv2.warpAffine(img, M, (cols, rows))

    # 5. 锐化
    if 'sharpen' in options:
        kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])  # 锐化卷积核
        img = cv2.filter2D(img, -1, kernel)

    # 6. 模糊
    if 'blur' in options:
        img = cv2.GaussianBlur(img, (5, 5), 0)

    # 7. 缩放
    if 'resize' in options:
        img = cv2.resize(img, (300, 300))  # 缩放至 300x300

    # 保存处理后的图片
    processed_path = os.path.join(PROCESSED_FOLDER, 'processed_image.jpg')
    cv2.imwrite(processed_path, img)

    return processed_path


# 图片处理功能
@process_image
def adjust_brightness(image, amount=0, **kwargs):
    """调整亮度"""
    factor = 1.0 + (float(amount) / 100.0)
    enhancer = ImageEnhance.Brightness(image)
    return enhancer.enhance(factor)

@process_image
def adjust_contrast(image, amount=0, **kwargs):
    """调整对比度"""
    factor = 1.0 + (float(amount) / 100.0)
    enhancer = ImageEnhance.Contrast(image)
    return enhancer.enhance(factor)

@process_image
def sharpen_image(image, amount=5, **kwargs):
    """锐化图像"""
    amount = min(max(int(amount), 1), 10)
    enhancer = ImageEnhance.Sharpness(image)
    return enhancer.enhance(1 + amount * 0.2)

@process_image
def blur_image(image, amount=3, **kwargs):
    """模糊图像"""
    amount = min(max(int(amount), 1), 10)
    return image.filter(ImageFilter.GaussianBlur(radius=amount))

@process_image
def rotate_image(image, angle=90, **kwargs):
    """旋转图像"""
    return image.rotate(angle, expand=True)

@process_image
def flip_image(image, direction='horizontal', **kwargs):
    """翻转图像"""
    if direction == 'horizontal':
        return ImageOps.mirror(image)
    elif direction == 'vertical':
        return ImageOps.flip(image)
    else:
        raise ValueError("方向参数必须是 'horizontal' 或 'vertical'")

@process_image
def crop_image(image, box, **kwargs):
    """裁剪图像"""
    try:
        box = tuple(map(int, box))
        width, height = image.size
        left, top, right, bottom = box
        
        if left < 0 or top < 0 or right > width or bottom > height:
            raise ValueError("裁剪区域超出图片范围")
        if left >= right or top >= bottom:
            raise ValueError("无效的裁剪区域")
            
        return image.crop(box)
    except Exception as e:
        raise ValueError(f"裁剪失败: {str(e)}")

@process_image
def convert_grayscale(image, **kwargs):
    """转换为灰度图"""
    return ImageOps.grayscale(image)

# 滤镜效果功能
@process_image
def apply_filter(image, filter_type='vintage', **kwargs):
    """应用滤镜效果"""
    img_array = np.array(image)
    
    if filter_type == 'vintage':
        # 复古效果
        r = img_array[:,:,0] * 0.393 + img_array[:,:,1] * 0.769 + img_array[:,:,2] * 0.189
        g = img_array[:,:,0] * 0.349 + img_array[:,:,1] * 0.686 + img_array[:,:,2] * 0.168
        b = img_array[:,:,0] * 0.272 + img_array[:,:,1] * 0.534 + img_array[:,:,2] * 0.131
        img_array = np.clip(np.dstack((r,g,b)), 0, 255).astype(np.uint8)
    
    elif filter_type == 'sepia':
        # 褐色效果
        img_array = img_array.dot([[0.393, 0.769, 0.189],
                                 [0.349, 0.686, 0.168],
                                 [0.272, 0.534, 0.131]])
        img_array = np.clip(img_array, 0, 255).astype(np.uint8)
    
    elif filter_type == 'cool':
        # 冷色调
        img_array = img_array.astype(np.float64)
        img_array[:,:,0] = img_array[:,:,0] * 0.8  # 减少红色
        img_array[:,:,2] = np.clip(img_array[:,:,2] * 1.2, 0, 255)  # 增加蓝色
        img_array = img_array.astype(np.uint8)
    
    elif filter_type == 'warm':
        # 暖色调
        img_array = img_array.astype(np.float64)
        img_array[:,:,0] = np.clip(img_array[:,:,0] * 1.2, 0, 255)  # 增加红色
        img_array[:,:,2] = img_array[:,:,2] * 0.8  # 减少蓝色
        img_array = img_array.astype(np.uint8)
    
    return Image.fromarray(img_array)

@process_image
def adjust_saturation(image, amount=0, **kwargs):
    """调整饱和度"""
    factor = 1.0 + (float(amount) / 100.0)
    enhancer = ImageEnhance.Color(image)
    return enhancer.enhance(factor)

@process_image
def adjust_hue(image, amount=0, **kwargs):
    """调整色相"""
    img_array = np.array(image.convert('HSV'))
    img_array[:,:,0] = (img_array[:,:,0] + amount) % 180
    return Image.fromarray(img_array, 'HSV').convert('RGB')

def batch_process(image_data, operations):
    """批量处理图像
    Args:
        image_data: base64编码的图片数据
        operations: 操作列表，每个操作是(函数, 参数字典)的元组
    Returns:
        str: 处理后的base64编码图像数据
    """
    result = image_data
    for func, params in operations:
        result = func(result, **params)
    return result

def balance_samples(images, target_size):
    """将图像样本调整为相同大小
    Args:
        images: 图像列表（base64编码）
        target_size: 目标尺寸元组 (width, height)
    Returns:
        list: 调整大小后的图像列表（base64编码）
    """
    balanced = []
    for img_data in images:
        img = Image.open(io.BytesIO(base64.b64decode(img_data.split(',')[1])))
        img = img.resize(target_size, Image.LANCZOS)
        buffered = io.BytesIO()
        img.save(buffered, format="PNG")
        balanced.append("data:image/png;base64," + base64.b64encode(buffered.getvalue()).decode())
    return balanced
